package com.lzc.springMvcPart;

import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.List;
import java.util.Map;

public class DispatchServletTest {
    public static void main(String[] args) throws Exception {
        // 支持内嵌web容器
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);

        // 初始化的时候获取到容器中controller中的路径和方法的映射关系
        RequestMappingHandlerMapping handlerMapping = context.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();

        System.out.println("------------------ 获取控制器方法与uri的对应关系 ---------------------------");
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
            System.out.println(entry.getKey()+"=="+entry.getValue());
        }

        System.out.println("-------------------RequestMappingHandlerMapping，根据uri获取对应的控制器方法链----------------------");
        MockHttpServletRequest request = new MockHttpServletRequest("GET", "/getToken");
        request.setParameter("args","test");
        request.addHeader("token","1234567890");
        MockHttpServletResponse response = new MockHttpServletResponse();

        // 根据请求路径获取处理方法,返回处理器执行链：包括拦截器，控制器方法等
        HandlerExecutionChain chain =
                handlerMapping.getHandler(request);
        System.out.println(chain);

        System.out.println("----------------------RequestMappingHandlerAdapter,调用控制器方法-------------------------------------");
        HandlerAdapterChild handlerAdapter = context.getBean(HandlerAdapterChild.class);
        ModelAndView modelAndView = handlerAdapter.invokeHandlerMethod(request, response, (HandlerMethod) chain.getHandler());
        System.out.println(modelAndView);

        // 解析方法中参数的注解是Adapter调用其他主键来进行处理的
        System.out.println("----------------------ArgumentResolvers，解析方法中的参数-------------------------------------");
        List<HandlerMethodArgumentResolver> argumentResolvers = handlerAdapter.getArgumentResolvers();
        System.out.println("size = " + argumentResolvers.size());
        for (HandlerMethodArgumentResolver argumentResolver : argumentResolvers) {
            System.out.println(argumentResolver);
        }

        System.out.println("----------------------HandlerMethodReturnValueHandler，返回值处理-------------------------------------");
        List<HandlerMethodReturnValueHandler> returnValueHandlers = handlerAdapter.getReturnValueHandlers();
        System.out.println("size = " + returnValueHandlers.size());
        for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
            System.out.println(returnValueHandler);
        }

    }

}
